﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Permissions;
using System.Threading;
using System.Web.Script.Serialization;
using System.Windows.Forms;
using NeteaseCloudMusic.Utils;

namespace NeteaseCloudMusic
{
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class Main : Form
    {
        public List<string> StandbyURL = new List<string> {
            "https://music.pdoner.cn/",
            "http://66666.kim/",
        };
        public WebBrowser myWebIE { get; set; }
        public HtmlDocument doc_WebIE { get; set; }
        public Elements_IE elem_WebIE { get; set; }
        public bool ExitToNotify { get; set; }
        public bool HasShowExitToNotify { get; set; }
        public bool AutoWork { get; set; }
        public DateTime AutoWorkDate { get; set; } = DateTime.MaxValue;
        public DateTime LastSignDate { get; set; } = DateTime.MaxValue;
        public static string Phone { get; set; }
        public static string Pwd { get; set; }
        public static int TryTimes { get; set; } = 5;
        public static int TryInterval { get; set; } = 30;
        public static int CurrentTimes { get; set; } = 1;
        public static string CurrentUrl { get; set; } = "https://music.pdoner.cn";

        public string strSikpSign { get; set; } = "跳过签到:距上次签到不足8小时";

        BackgroundWorker bgw;
        System.Timers.Timer autoWorkTimer;
        System.Timers.Timer tryAgainTimer;
        public Main()
        {
            InitializeComponent();
            try
            {
                Icon = Properties.Resources.打卡;
                btnSign.Enabled = false;
                Assembly asm = Assembly.GetExecutingAssembly();
                FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(asm.Location);
                this.Text += $"  v{fvi.ProductVersion}";
                notify.Icon = Properties.Resources.打卡;
                notify.Text = this.Text;
                curVerToolStripMenuItem.Text = $"版本v{fvi.ProductVersion}";
                IniHelper.defaultSection = "pdone";

                if (!File.Exists(IniHelper.filePath))
                {
                    IniHelper.WriteSetting("AutoWork", AutoWork);
                    IniHelper.WriteSetting("ExitToNotify", ExitToNotify);
                    IniHelper.WriteSetting("HasShowExitToNotify", HasShowExitToNotify);
                    IniHelper.WriteSetting("Url", CurrentUrl);
                    IniHelper.WriteSetting("TryTimes", 5);
                    IniHelper.WriteSetting("TryInterval", 30);//秒
                    IniHelper.WriteSetting("AutoWorkDate", DateTime.Now.ToString("yyyyMMdd") + new Random().Next(10, 23) + new Random().Next(10, 59) + new Random().Next(10, 59));//秒

                    var tempList = new List<string> {
                    "建议不要手动修改这里的东西。如果不小心改错了，直接删除就好了，不过之前的设置就没有了",
                    "备用Url" ,
                    "http://66666.kim/" ,
                    "https://music.pdoner.cn"
                    };

                    tempList = tempList.Select(x => x = ";" + x).ToList();
                    File.AppendAllLines(IniHelper.filePath, tempList);
                }

                AutoWork = IniHelper.GetBoolSetting("AutoWork");
                ExitToNotify = IniHelper.GetBoolSetting("ExitToNotify");
                HasShowExitToNotify = IniHelper.GetBoolSetting("HasShowExitToNotify");
                Phone = IniHelper.GetSetting("Phone");
                Pwd = IniHelper.GetSetting("Pwd");
                LastSignDate = IniHelper.GetDateSetting("LastSignDate");
                AutoWorkDate = IniHelper.GetDateSetting("AutoWorkDate");
                TryTimes = IniHelper.GetIntSetting("TryTimes");
                TryInterval = IniHelper.GetIntSetting("TryInterval");
                CurrentUrl = IniHelper.GetSetting("Url");

                WebBrowser webIE = new WebBrowser
                {
                    Dock = DockStyle.Fill
                };
                myWebIE = webIE;
                myWebIE.Url = new Uri(CurrentUrl);
                myWebIE.DocumentCompleted += MyWebIE_DocumentCompleted;

                panel1.Controls.Add(myWebIE);

                bgw = new BackgroundWorker();
                bgw.DoWork += Bgw_DoWork;

                autoWorkTimer = new System.Timers.Timer();
                autoWorkTimer.Interval = 1000;
                autoWorkTimer.Elapsed += AutoWorkTimer_Elapsed;
                if (AutoWork)
                {
                    timePacker.Enabled = true;
                    autoWorkTimer.Enabled = true;
                    autoWorkTimer.Start();
                }

                tryAgainTimer = new System.Timers.Timer();
                tryAgainTimer.Interval = TryInterval * 1000;
                tryAgainTimer.Elapsed += TryAgainTimer_Elapsed;

                cbx3.Checked = AutoWork;
                tbxPhone.Text = Phone;
                tbxPwd.Text = Pwd;
                timePacker.Value = AutoWorkDate;
                numericUpDown1.Value = TryTimes;
                numericUpDown2.Value = TryInterval;
                tbxUrl.Text = CurrentUrl;
                最小化到系统托盘ToolStripMenuItem.Checked = ExitToNotify;

                Warning warning = new Warning();
                warning.ShowDialog();
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                Extent.ShowMsg("启动失败，手动删除配置文件后重新打开试试，并将logs文件发给我");
            }
        }

        private void MyWebIE_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (myWebIE.Document == null)
            {
                Extent.ShowMsg("遇到了未知的问题");
            }
            doc_WebIE = myWebIE.Document;

            elem_WebIE = new Elements_IE
            {
                UserName = doc_WebIE.GetElementById("uin"),
                Password = doc_WebIE.GetElementById("pwd"),
                BtnLogin = doc_WebIE.GetElementById("submit"),
            };
        }

        private void TryAgainTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (CurrentTimes <= TryTimes)
            {
                AddRow($"当前进度({CurrentTimes}/{TryTimes})");
                Sign();
                Sing300Music();
                CurrentTimes++;

                if (CurrentTimes > TryTimes)
                {
                    AddRow($"本轮结束 共执行{TryTimes}次");
                    tryAgainTimer.Enabled = false;
                    tryAgainTimer.Stop();
                }
            }
        }

        private void AutoWorkTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            // 得到intHour,intMinute,intSecond，是当前系统时间    
            int intHour = e.SignalTime.Hour;
            int intMinute = e.SignalTime.Minute;
            int intSecond = e.SignalTime.Second;
            if (intHour == timePacker.Value.Hour &&
                intMinute == timePacker.Value.Minute &&
                intSecond == timePacker.Value.Second)
            {
                AddRow($"定时执行开始");
                Login();
                bgw.RunWorkerAsync();
            }
        }

        private void Bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.Sleep(1500);
            btn1_Click(null, EventArgs.Empty);
        }

        /// <summary>
        /// 登录按钮点击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn0_Click(object sender, EventArgs e)
        {
            if (tbxPhone.Text.IsNullOrWhiteSpace())
            {
                AddRow("手机号不能为空");
                return;
            }
            if (tbxPwd.Text.IsNullOrWhiteSpace())
            {
                AddRow("密码不能为空");
                return;
            }
            Login();
        }

        /// <summary>
        /// 签到 + 听歌300首
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn1_Click(object sender, EventArgs e)
        {
            CurrentTimes = 1;
            AddRow($"将执行{TryTimes}次 当前进度({CurrentTimes}/{TryTimes})");
            strSikpSign = "跳过签到:距上次签到不足8小时";
            Sign();
            Sing300Music();
            CurrentTimes++;
            tryAgainTimer.Enabled = true;
            tryAgainTimer.Start();
        }

        /// <summary>
        /// 签到
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Sign()
        {
            try
            {
                LastSignDate = IniHelper.GetDateSetting("LastSignDate");
                //从未签到过  或者上次签到早于8个小时前
                if (LastSignDate == DateTime.MaxValue || DateTime.Now.Subtract(LastSignDate).TotalHours > 8)
                {
                    elem_WebIE.BtnSign = doc_WebIE.GetElementById("sign");
                    if (elem_WebIE.BtnSign.ButtonClick())
                    {
                        AddRow("执行签到");
                    }
                    IniHelper.WriteSetting("LastSignDate", DateTime.Now.ToString("yyyyMMddHHmmss"));
                    Thread.Sleep(500);
                }
                else
                {
                    AddRow(strSikpSign);
                    strSikpSign = "";
                }
            }
            catch (Exception)
            { }
        }

        /// <summary>
        /// 听歌300首
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Sing300Music()
        {
            try
            {
                elem_WebIE.BtnClock = doc_WebIE.GetElementById("daka");
                if (elem_WebIE.BtnClock.ButtonClick())
                {
                    AddRow("执行听歌300首");
                }
            }
            catch (Exception)
            { }
        }

        /// <summary>
        /// 登录
        /// </summary>
        private void Login()
        {
            try
            {
                Phone = tbxPhone.Text.Trim();
                Pwd = tbxPwd.Text.Trim();
                if (Phone.IsNullOrWhiteSpace() || Pwd.IsNullOrWhiteSpace())
                {
                    AddRow("手机号或密码不能为空");
                    return;
                }
                AddRow("登录");

                IniHelper.WriteSetting("Phone", Phone);
                IniHelper.WriteSetting("Pwd", Pwd);
                elem_WebIE.UserName.InputValue(Phone);
                elem_WebIE.Password.InputValue(Pwd);
                if (elem_WebIE.BtnLogin.ButtonClick())
                {
                    btnSign.Enabled = true;
                }
            }
            catch (Exception)
            { }
        }
        public void AddRow(string text)
        {
            if (text.IsNullOrWhiteSpace())
            {
                return;
            }
            listBox1.AddRow(text);
        }

        private void cbx3_CheckedChanged(object sender, EventArgs e)
        {
            AutoWork = cbx3.Checked;
            IniHelper.WriteSetting("AutoWork", AutoWork);
            if (AutoWork)
            {
                timePacker.Enabled = true;
                autoWorkTimer.Enabled = true;
                autoWorkTimer.Start();
            }
            else
            {
                timePacker.Enabled = false;
                autoWorkTimer.Stop();
                autoWorkTimer.Enabled = false;
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://music.163.com/#/user/level");
        }

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            //Clipboard.SetText("%AppData%\\NeteaseCloudMusic");
            About about = new About();
            about.Icon = Properties.Resources.打卡;
            about.StartPosition = FormStartPosition.CenterParent;
            about.ShowDialog();
        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            TryTimes = (int)numericUpDown1.Value;
            IniHelper.WriteSetting("TryTimes", TryTimes);
        }

        private void numericUpDown2_ValueChanged(object sender, EventArgs e)
        {
            TryInterval = (int)numericUpDown2.Value;
            tryAgainTimer.Interval = TryInterval * 1000;
            IniHelper.WriteSetting("TryInterval", TryInterval);
        }

        private void timePacker_ValueChanged(object sender, EventArgs e)
        {
            AutoWorkDate = timePacker.Value;
            IniHelper.WriteSetting("AutoWorkDate", AutoWorkDate.ToString("yyyyMMddHHmmss"));//秒
        }

        private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            listBox1.Items.Clear();
        }

        private void tbxUrl_TextChanged(object sender, EventArgs e)
        {

        }

        private void linkLabel4_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                CurrentUrl = tbxUrl.Text.Trim();
                IniHelper.WriteSetting("Url", CurrentUrl);
                myWebIE.Navigate(new Uri(CurrentUrl));
            }
            catch (Exception ex)
            {
                AddRow(ex.Message);
            }
        }

        private void Main_Load(object sender, EventArgs e)
        {

        }

        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult dr = DialogResult.No;
            if (ExitToNotify)
            {
                dr = DialogResult.Yes;
            }
            else
            {
                if (!HasShowExitToNotify)
                {
                    dr = MessageBox.Show("最小化到系统托盘？", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    IniHelper.WriteSetting("HasShowExitToNotify", true);
                }
            }
            switch (dr)
            {
                case DialogResult.Yes:
                    e.Cancel = true;
                    this.Hide();
                    break;
                case DialogResult.No:
                    this.Dispose();
                    this.Close();
                    break;
                default:
                    break;
            }
            notify.Tag = this;
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Dispose();
            this.Close();
        }

        private void 最小化到系统托盘ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ExitToNotify = !ExitToNotify;
            最小化到系统托盘ToolStripMenuItem.Checked = ExitToNotify;
            IniHelper.WriteSetting("ExitToNotify", ExitToNotify);
        }

        private void notify_Click(object sender, EventArgs e)
        {
            if ((e as MouseEventArgs).Button == MouseButtons.Left)
            {
                this.Activate();
                this.Show();
            }
        }

        private void 项目地址ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("https://gitee.com/pdone/NeteaseCloudMusic");
        }

        private void linkFAQ_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            UseFAQ useFAQ = new UseFAQ();
            useFAQ.ShowDialog();
        }
    }

    public class Elements_IE
    {
        /// <summary>
        /// 用户名输入框
        /// </summary>
        public HtmlElement UserName;
        /// <summary>
        /// 密码输入框
        /// </summary>
        public HtmlElement Password;
        /// <summary>
        /// 登录按钮
        /// </summary>
        public HtmlElement BtnLogin;
        /// <summary>
        /// 签到按钮
        /// </summary>
        public HtmlElement BtnSign;
        /// <summary>
        /// 打卡按钮
        /// </summary>
        public HtmlElement BtnClock;

    };

    public static class Extent
    {
        #region DataGridView添加行
        public delegate void DataGridViewRow(DataGridView dgv, string Content);

        public static void AddDataGridViewRowFunc(DataGridView dgv, string Content)
        {
            dgv.ClearSelection();
            int index = dgv.Rows.Add();
            dgv.Rows[index].Cells[1].Value = DateTime.Now.ToString("HH:mm:ss");
            dgv.Rows[index].Cells[2].Value = Content;
            dgv.Rows[index].Selected = true;
            dgv.FirstDisplayedScrollingRowIndex = index;
        }
        public static void AddRow(this DataGridView dgv, string Content)
        {
            if (dgv.InvokeRequired)
            {
                dgv.Invoke(new DataGridViewRow(AddDataGridViewRowFunc), dgv, Content);
            }
            else
            {
                dgv.ClearSelection();
                int index = dgv.Rows.Add();
                dgv.Rows[index].Cells[1].Value = DateTime.Now.ToString("HH:mm:ss");
                dgv.Rows[index].Cells[2].Value = Content;
                dgv.Rows[index].Selected = true;
                dgv.FirstDisplayedScrollingRowIndex = index;
            }
        }
        #endregion

        #region ListBox添加项
        public delegate void AddListItemHandle(ListBox listBox, string Content);

        public static void AddListItemFunc(ListBox listBox, string Content)
        {
            listBox.ClearSelected();
            int index = listBox.Items.Add($"{DateTime.Now.ToString("HH:mm:ss")} {Content}");
            listBox.SelectedIndex = index;
        }
        public static void AddRow(this ListBox listBox, string Content)
        {
            if (listBox.InvokeRequired)
            {
                listBox.Invoke(new AddListItemHandle(AddListItemFunc), listBox, Content);
            }
            else
            {
                listBox.ClearSelected();
                int index = listBox.Items.Add($"{DateTime.Now.ToString("HH:mm:ss")} {Content}");
                listBox.SelectedIndex = index;
            }
        }
        #endregion      

        #region
        public static bool InputValue(this HtmlElement element, string value)
        {
            if (element == null)
            {
                //ShowMsg("请先登录");
                return false;
            }
            element.SetAttribute("value", value);
            Thread.Sleep(100);
            return true;
        }

        public static bool ButtonClick(this HtmlElement element)
        {
            if (element == null)
            {
                //ShowMsg("请先登录");
                return false;
            }
            element.InvokeMember("click");
            Thread.Sleep(100);
            return true;
        }
        #endregion

        public static DialogResult ShowMsg(string text, string caption = "提示", MessageBoxButtons buttons = MessageBoxButtons.OK, MessageBoxIcon icon = MessageBoxIcon.Information)
        {
            return MessageBox.Show(text, caption, buttons, icon);
        }

        /// <summary>
        /// 指示指定的字符串是 null、空还是仅由空白字符组成。
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNullOrWhiteSpace(this string str)
        {
            if (string.IsNullOrWhiteSpace(str))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
